package com.turing.model.caller.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.turing.common.config.ServerConfig;
import com.turing.common.response.ResponseVO;
import com.turing.common.response.model.ResVO;
import com.turing.common.util.HttpUtils;
import com.turing.model.caller.client.task.manager.DrawClient;
import com.turing.model.caller.rules.IRule;
import com.turing.model.caller.service.DrawService;
import com.turing.model.caller.utils.SpringUtil;
import com.turing.model.caller.vo.in.*;
import com.turing.model.caller.vo.out.AnalysisParamsVo;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.*;

@Component
public class AnalysisCallerHandler {

    @Autowired
    private DrawClient drawClient;

    @Autowired
    private ServerConfig serverConfig;

    @Autowired
    private DrawService drawService;

    @Value("${producer.clients:}")
    private List<String> clients;

    @Value("${loadBalance.rule}")
    private String balanceRule;

    private static final Logger logger = LoggerFactory.getLogger(AnalysisCallerHandler.class);

    // reuse xxl-job handler by set different host
    @XxlJob(value="callAnalysisJobHandler")
    public void callOCRModel() {

        // choose client 通过cas自旋锁来保证原子性的操作
        IRule rule = (IRule) SpringUtil.getBean(balanceRule);
        //获取不同的client:com.turing.model.caller.client.task.manager
        String client = rule.choose(clients);

        // try to get task
        String url = serverConfig.getUrl();
        //通过反射去调用不同的方法
        ResponseVO<FileTaskVo> getResVO = drawService.getAndLockAnalysisTask(url,client);
        if(getResVO != null && getResVO.getCode().equals("200")){
            FileTaskVo fileTaskVo = getResVO.getData();
            if(fileTaskVo == null){
                // retry
                client = rule.choose(clients);
                getResVO = drawService.getAndLockAnalysisTask(url,client);
                if(getResVO.getCode().equals("200")){
                    fileTaskVo = getResVO.getData();
                }
            }
            if(fileTaskVo != null && !fileTaskVo.equals(new FileTaskVo())){

                String parentTaskSn = fileTaskVo.getParentTaskSn();
                String taskSn = fileTaskVo.getTaskSn();
                String fileUrl = fileTaskVo.getPdfUrl();
                String fileName = fileTaskVo.getFileName();
                logger.info("==========>callAnalysisJobHandler,taskSn="+taskSn);
                // call model
                String param = XxlJobHelper.getJobParam();
                String[] split = param.split("_");

                // test model ok
                String httpUrl = "http://" +split[0] + "/api/model/pdfocr";
                logger.info("==========>callAnalysisJobHandler,httpUrl="+httpUrl);
                httpUrl="http://127.0.0.1:1101/api/model/pdfocr";
                AnalysisParamsVo callParam = AnalysisParamsVo.builder()
                        .task_id(taskSn)
                        .file_id(fileUrl).file_name(fileName).build();
                int readTimeOut = 900000;
                String params = JSON.toJSONString(callParam);
                long tid = Thread.currentThread().getId();
                logger.info("starting call analysis model..param is:"+params,"thread id is:"+tid);
                String res = "";
                try{
                    res = HttpUtils.doPost(httpUrl,params,readTimeOut);
                }catch (Exception e){
                    logger.error(e.getMessage());
                    unlockTask(taskSn,client);
                    return;
                }

                ResVO<String> ocrResVo = JSONObject.parseObject(res, new TypeReference<ResVO<String>>(){});
                String resCode = ocrResVo.getCode();
                logger.info("thread id is:"+tid+","+"resCode is:"+resCode);
                if(resCode.equals("0")){
                    String analysisEntityStr = ocrResVo.getData();
                    AnalysisEntityVo AnalysisEntityVo = JSONObject.parseObject(analysisEntityStr, AnalysisEntityVo.class);

                    AnalysisResultVo analysisResultVo = AnalysisResultVo.builder()
                            .parentTaskSn(parentTaskSn)
                            .taskSn(taskSn)
                            .ocrJsonUrl(AnalysisEntityVo.getJson_file_id())
                            .build();
                    drawService.analysisCallback(analysisResultVo,client);

                }else{
                    unlockTask(taskSn,client);
                }
            }
        }
    }

    private void unlockTask(String taskSn,String client) {
        ResponseVO<Object> responseOk = null;
        try{
            responseOk = drawService.unLockAnalysisTask(taskSn,client);
        }catch (Exception e1){
            logger.error(e1.getMessage());
        }
        assert responseOk != null;
        logger.info("unlock result:"+responseOk.getData().toString());
    }

}
